from util import do, do_bare


class RGit:
    BRANCH_CURRENT = 1
    BRANCH_LOCAL = 2
    BRANCH_REMOTE = 3
    BRANCH_TYPE = (BRANCH_CURRENT, BRANCH_LOCAL, BRANCH_REMOTE)

    br_args_dict = {BRANCH_CURRENT: ['branch', '--no-color', '-v', '--abbrev=6', '--contains'],
                    BRANCH_LOCAL: ['branch', '--no-color', '-v', '--abbrev=6'],
                    BRANCH_REMOTE: ['branch', '--no-color', '-v', '--abbrev=6', '-r']}

    def __init__(self, repo: str):
        self._repo = repo

    def branch(self, br_type: int = BRANCH_LOCAL) -> []:
        args = ['git', '-C', self._repo] + RGit.br_args_dict[br_type]
        c = do_bare(args)
        # parse the completed output
        lines = str(c.stdout, 'utf-8').split('\n')
        if br_type == self.BRANCH_CURRENT:
            for i in range(len(lines)):
                if '*' not in lines[i]:
                    lines[i] = ''
        lines = [line.lstrip('*').strip() for line in lines if line
                 and 'origin/HEAD' not in line]
        o = []
        for line in lines:
            a = line.split()
            o.append({
                'full_name': a[0],
                'base_name': a[0].split('/')[-1],
                'commit_id': a[1],
                'commit': ' '.join(a[2:])
            })
        return o

    def stash(self):
        args = ['git', '-C', self._repo, 'stash']
        self.do_wrap(args)

    def stash_pop(self):
        args = ['git', '-C', self._repo, 'stash', 'pop']
        self.do_wrap(args)

    def restore_worktree(self):
        args = ['git', '-C', self._repo, 'checkout', '.']
        self.do_wrap(args)

    def switch_local_branch(self, local: str = None):
        args = ['git', '-C', self._repo, 'checkout', local]
        self.do_wrap(args)
        self.pull()

    def do_wrap(self, args):
        args = ['/tmp/git_log.txt'] + args
        return do(args)

    def fetch_remote_branch(self, remote: str, local: str = None):
        if not local:
            local = remote.split('/')[1]
        cur_locals = self.branch(RGit.BRANCH_LOCAL)
        for l in cur_locals:
            if local == l['full_name']:
                self.switch_local_branch(local)
                return
        self.restore_worktree()
        args = ['git', '-C', self._repo, 'checkout', '-b', local, remote]
        self.do_wrap(args)
        self.pull()

    def reset(self):
        args = ['git', '-C', self._repo, 'reset', 'HEAD', '--hard']
        self.do_wrap(args)

    def pull(self):
        args = ['git', '-C', self._repo, 'pull']
        self.do_wrap(args)

    def apply(self, patch: str):
        args = ['git', '-C', self._repo, 'apply', patch]
        self.do_wrap(args)

    def commit(self, m: str):
        args = ['git','-C', self._repo, 'commit',  '-a', '-m', m]
        self.do_wrap(args)

    def push(self):
        args = ['git','-C', self._repo, 'push']
        self.do_wrap(args)

    def update(self):
        self.restore_worktree()
        self.pull()
